/*
* Copyright (C) 2008-2009 J-P Nurmi jpnurmi@gmail.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* $Id: completionmodel.cpp 350 2009-04-27 18:58:11Z jpnurmi $
*/

#include "completionmodel.h"
#include "messageparser.h"

CompletionModel::CompletionModel(QObject* parent)
    : QAbstractListModel(parent)
{
    init();
}

CompletionModel::CompletionModel(const QModelIndex& index, QObject* parent)
    : QAbstractListModel(parent)
{
    init();
    setCompletionIndex(index);
}

QModelIndex CompletionModel::completionIndex() const
{
    return d.index;
}

void CompletionModel::setCompletionIndex(const QModelIndex& index)
{
    if (d.index != index)
    {
        const QAbstractItemModel* prev = d.index.model();
        const QAbstractItemModel* next = index.model();

        if (prev != next)
        {
            if (prev)
            {
                disconnect(prev, SIGNAL(columnsInserted(QModelIndex,int,int)), this, SLOT(onColumnsInserted(QModelIndex,int,int)));
                disconnect(prev, SIGNAL(columnsRemoved(QModelIndex,int,int)), this, SLOT(onColumnsRemoved(QModelIndex,int,int)));
                disconnect(prev, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(onDataChanged(QModelIndex,QModelIndex)));
                disconnect(prev, SIGNAL(layoutChanged()), this, SLOT(onLayoutChanged()));
                disconnect(prev, SIGNAL(modelReset()), this, SLOT(onModelReset()));
                disconnect(prev, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(onRowsInserted(QModelIndex,int,int)));
                disconnect(prev, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(onRowsRemoved(QModelIndex,int,int)));
            }

            if (next)
            {
                connect(next, SIGNAL(columnsInserted(QModelIndex,int,int)), this, SLOT(onColumnsInserted(QModelIndex,int,int)));
                connect(next, SIGNAL(columnsRemoved(QModelIndex,int,int)), this, SLOT(onColumnsRemoved(QModelIndex,int,int)));
                connect(next, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(onDataChanged(QModelIndex,QModelIndex)));
                connect(next, SIGNAL(layoutChanged()), this, SLOT(onLayoutChanged()));
                connect(next, SIGNAL(modelReset()), this, SLOT(onModelReset()));
                connect(next, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(onRowsInserted(QModelIndex,int,int)));
                connect(next, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(onRowsRemoved(QModelIndex,int,int)));
            }
        }

        d.index = index;
        reset();
    }
}

int CompletionModel::rowCount(const QModelIndex& parent) const
{
    if (!d.index.model() || parent.isValid())
        return 0;

    if (d.users == -1)
        d.users = d.index.model()->rowCount(d.index);
    if (d.channels == -1)
        d.channels = d.index.model()->rowCount(d.index.parent());
    return d.users + d.channels + d.commands.count() + d.aliases.count();
}

QVariant CompletionModel::data(const QModelIndex& index, int role) const
{
    if (d.users == -1)
        d.users = d.index.model()->rowCount(d.index);
    if (d.channels == -1)
        d.channels = d.index.model()->rowCount(d.index.parent());

    int row = index.row();
    if (row < d.users)
        return d.index.child(row, index.column()).data(role);

    row -= d.users;
    if (row < d.channels)
        return d.index.sibling(row, index.column()).data(role);

    static const QList<int> roles = QList<int>() << Qt::DisplayRole << Qt::EditRole;

    row -= d.channels;
    if (row < d.commands.count())
    {
        if (roles.contains(role) || role >= Qt::UserRole)
            return d.commands.at(row);
        return QVariant();
    }

    row -= d.commands.count();
    if (row < d.aliases.count())
    {
        if (roles.contains(role) || role >= Qt::UserRole)
            return d.aliases.at(row);
    }

    return QVariant();
}

void CompletionModel::onColumnsInserted(const QModelIndex& parent, int start, int end)
{
    // TODO
    reset();
}

void CompletionModel::onColumnsRemoved(const QModelIndex& parent, int start, int end)
{
    // TODO
    reset();
}

void CompletionModel::onDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight)
{
    // TODO
    reset();
}

void CompletionModel::onLayoutChanged()
{
    // TODO
    reset();
}

void CompletionModel::onModelReset()
{
    // TODO
    reset();
}

void CompletionModel::onRowsInserted(const QModelIndex& parent, int start, int end)
{
    // TODO
    reset();
}

void CompletionModel::onRowsRemoved(const QModelIndex& parent, int start, int end)
{
    // TODO
    reset();
}

void CompletionModel::init()
{
    d.aliases = Alias::aliases();
    QMutableStringListIterator it1(d.aliases);
    while (it1.hasNext())
        it1.next().prepend("/");
    d.commands = MessageParser::commands();
    QMutableStringListIterator it2(d.commands);
    while (it2.hasNext())
        it2.next().prepend("/");
    d.channels = -1;
    d.users = -1;
}

void CompletionModel::reset()
{
    d.channels = -1;
    d.users = -1;
    QAbstractItemModel::reset();
}
